package config

import (
	jsoniter "github.com/json-iterator/go"
	"io/ioutil"
	"log"
	"os"
	"strings"
)

//Config配置
type Config struct {
	AppInfo   appInfo   `json:"AppInfo"`
	Log       logConf   `json:"Log"`
	DB        db        `json:"DB"`
	Redis     redis     `json:"Redis"`
	Security  security  `json:"Security"`
	EmailInfo emailInfo `json:"EmailInfo"`
	Wechat    wechat    `json:"Wechat"`
	Qiniu     qiniu     `json:"Qiniu"`
}

type appInfo struct {
	Env    string `json:"Env"` // example: local, dev, prod
	Slogan string `json:"Slogan"`
	Addr   string `json:"Addr"`
}

type logConf struct {
	LogBasePath string `json:"LogBasePath"`
	LogFileName string `json:"LogFileName"`
}

type security struct {
	Secret string `json:"Secret"`
}

type emailInfo struct {
	From     string   `json:"From"`
	To       []string `json:"To"`
	UserName string   `json:"UserName"`
	AuthCode string   `json:"AuthCode"`
	Host     string   `json:"Host"`
}

type wechat struct {
	AppID     string `json:"AppID"`
	AppSecret string `json:"AppSecret"`
}

type qiniu struct {
	AccessKey string `json:"AccessKey"`
	SecretKey string `json:"SecretKey"`
	Bucket    string `json:"Bucket"` // 空间
}

type db struct {
	DriverName  string `json:"DriverName"`
	Host        string `json:"Host"`
	Port        string `json:"Port"`
	DBName      string `json:"DBName"`
	User        string `json:"User"`
	PW          string `json:"PW"`
	AdminDBName string `json:"AdminDBName"`
}

type redis struct {
	Host string `json:"Host"`
	Port string `json:"Port"`
	PW   string `json:"PW"`
}

type BusAndRoutes struct {
	BusRoute map[string]int `json:"bus_route"` //公交车名字对路线下标的映射
	Routes   []Route        `json:"routes"`    //路线数组
}
type Route struct {
	Name           string    `json:"name"`           //路线名字
	Points         []Station `json:"points"`         //所有节点
	OppositePoints []Station `json:"oppositePoints"` //反向所有节点
}

type Part struct {
	IsDot bool   `json:"isDot"`
	Begin string `json:"begin"`
	End   string `json:"end"`
}

type Station struct {
	WGS84Lat       float64 `json:"wgs84_lat"`        //纬度  WGS84
	WGS84lon       float64 `json:"wgs84_lon"`        //经度  WGS84
	GCJ02Lat       float64 `json:"gcj02_lat"`        //纬度  GCJ02
	GCJ02Lon       float64 `json:"gcj02_lon"`        //经度  GCJ02
	X              float64 `json:"x"`                //x坐标
	Y              float64 `json:"y"`                //y坐标
	PreStaDistance float64 `json:"pre_sta_distance"` //上一站距离
	LasStaDistance float64 `json:"las_sta_distance"` //下一站距离
	Name           string  `json:"name"`             //站名
	Flag           int     `json:"flag"`             //为1时为校车站点，为0时表示仅为路线上一个节点
	Route          []int   `json:"route"`            //归属路线
	StationNum     float64 `json:"station_num"`      //和校车之间的站数,包括当前站数
}

type FrontEndRoutes struct {
	Routes []FrontEndRoute `json:"routes"`
}
type FrontEndRoute struct {
	Id            int    `json:"id"`
	BeginLocation string `json:"beginLocation"`
	EndLocation   string `json:"endLocation"`
	BeginTime     string `json:"beginTime"`
	EndTime       string `json:"endTime"`
	Interval      string `json:"interval"`
}

type FrontEnd struct {
	Stations map[string]FrontEndStation `json:"stations"`
}
type FrontEndStation struct {
	Route     []int   `json:"route"`
	Latitude  float64 `json:"latitude"`
	Longitude float64 `json:"longitude"`
	Name      string  `json:"name"`
}

type BusMessages struct {
	BusToId    map[string]int `json:"bus_to_id"`
	BusMessage []BusMessage   `json:"bus_message"`
}
type BusMessage struct {
	Result       int    `json:"result"`        //上一次判断的方向
	BusDirection [4]int `json:"bus_direction"` //前四次路线方向

	BusDis float64 `json:"bus_dis"` //上一次与出发站的距离

	PreGPS_WGS84 [2]float64 `json:"pre_gps"` //上一次get到的gps数组
	PreGPS_GCJ02 [2]float64

	BusMovQueue   [QUEUELENG]float64 `json:"bus_mov_queue"`   //每次移动距离队列
	BusMovQueuepr int                `json:"bus_mov_queuepr"` //队列指针

	BusDriveDir int `json:"bus_drive_dir"` //上一次的行驶方向 0为南北 1为东西
}

type Lines struct {
	Data []Line `json:"data"`
}
type Line struct {
	Id             int     `json:"id"`
	Points         []Point `json:"points"`
	OppositePoints []Point `json:"oppositePoints"`
	Color          string  `json:"color"`
	Parts          []Part  `json:"parts"`
	OppositeParts  []Part  `json:"oppositeParts"`
}
type Point struct {
	Route     []int   `json:"route"`
	Name      string  `json:"name"`
	Latitude  float64 `json:"latitude"`
	Longitude float64 `json:"longitude"`
}

//Conf 配置
var Conf *Config                   //项目配置
var Rou *BusAndRoutes              //公交车信息及线路信息
var Frondend *FrontEnd             //前端要用
var Frontendroutes *FrontEndRoutes //前端要用.
var Busmessages *BusMessages       //每一辆车的及时信息
var LineS *Lines                   //前端要用

var filePrefix = "/app/project/config"
var local = 1

func init() {
	log.Println("begin init all configs")
	initConf()
	initRoute()
	initFrontEnd()
	initFrontEndRoutes()
	initBusMessage()
	initLine()
	log.Println("over init all configs")
}

func initLine() {
	log.Println("begin init default Line config")
	LineS = &Lines{}
	fileName := "Line.json"

	if local == 0 {
		if v, ok := os.LookupEnv("CONFIG_PATH_PREFIX"); ok {
			filePrefix = v
		}
		// read route
		data, err := ioutil.ReadFile(filePrefix + fileName)
		if err != nil {
			log.Println("route-initConf: read Line.json error")
			log.Panic(err)
			return
		}
		err = jsoniter.Unmarshal(data, LineS)
		if err != nil {
			log.Println("route-initConf: unmarshal Line.json error")
			log.Panic(err)
			return
		}
	} else {
		// read route
		data, err := ioutil.ReadFile("D:\\Hustbus\\src\\config\\Line.json")
		if err != nil {
			log.Println("route-initConf: read Line.json error")
			log.Panic(err)
			return
		}
		err = jsoniter.Unmarshal(data, LineS)
		if err != nil {
			log.Println("route-initConf: unmarshal Line.json error")
			log.Panic(err)
			return
		}
	}
	log.Println("over init default Line config")
}

func initBusMessage() {
	log.Println("begin init default BusMessage config")
	Busmessages = &BusMessages{}
	fileName := "busmessage.json"

	if local == 0 {
		if v, ok := os.LookupEnv("CONFIG_PATH_PREFIX"); ok {
			filePrefix = v
		}
		// read route
		data, err := ioutil.ReadFile(filePrefix + fileName)
		if err != nil {
			log.Println("route-initConf: read busmessage.json error")
			log.Panic(err)
			return
		}
		err = jsoniter.Unmarshal(data, Busmessages)
		if err != nil {
			log.Println("route-initConf: unmarshal busmessage.json error")
			log.Panic(err)
			return
		}
	} else {
		// read route
		data, err := ioutil.ReadFile("D:\\Hustbus\\src\\config\\busmessage.json")
		if err != nil {
			log.Println("route-initConf: read busmessage.json error")
			log.Panic(err)
			return
		}
		err = jsoniter.Unmarshal(data, Busmessages)
		if err != nil {
			log.Println("route-initConf: unmarshal busmessage.json error")
			log.Panic(err)
			return
		}
	}
	log.Println("over init default BusMessage config")
}

func initFrontEndRoutes() {
	log.Println("begin init default frontendroute config")
	Frontendroutes = &FrontEndRoutes{}
	fileName := "Frontendroute.json"

	if local == 0 {
		if v, ok := os.LookupEnv("CONFIG_PATH_PREFIX"); ok {
			filePrefix = v
		}
		// read route
		data, err := ioutil.ReadFile(filePrefix + fileName)
		if err != nil {
			log.Println("route-initConf: read Frontendroute.json error")
			log.Panic(err)
			return
		}
		err = jsoniter.Unmarshal(data, Frontendroutes)
		if err != nil {
			log.Println("route-initConf: unmarshal Frontendroute.json error")
			log.Panic(err)
			return
		}
	} else {
		// read route
		data, err := ioutil.ReadFile("D:\\Hustbus\\src\\config\\Frontendroute.json")
		if err != nil {
			log.Println("route-initConf: read Frontendroute.json error")
			log.Panic(err)
			return
		}
		err = jsoniter.Unmarshal(data, Frontendroutes)
		if err != nil {
			log.Println("route-initConf: unmarshal Frontendroute.json error")
			log.Panic(err)
			return
		}
	}
	log.Println("over init default frontendroute config")
}

func initFrontEnd() {
	log.Println("begin init default Frondend config")
	Frondend = &FrontEnd{}
	fileName := "Station.json"

	if local == 0 {
		if v, ok := os.LookupEnv("CONFIG_PATH_PREFIX"); ok {
			filePrefix = v
		}
		// read route
		data, err := ioutil.ReadFile(filePrefix + fileName)
		if err != nil {
			log.Println("route-initConf: read Station.json error")
			log.Panic(err)
			return
		}
		err = jsoniter.Unmarshal(data, Frondend)
		if err != nil {
			log.Println("route-initConf: unmarshal Station.json error")
			log.Panic(err)
			return
		}
	} else {
		// read route
		data, err := ioutil.ReadFile("D:\\Hustbus\\src\\config\\Station.json")
		if err != nil {
			log.Println("route-initConf: read Station.json error")
			log.Panic(err)
			return
		}
		err = jsoniter.Unmarshal(data, Frondend)
		if err != nil {
			log.Println("route-initConf: unmarshal Station.json error")
			log.Panic(err)
			return
		}
	}
	log.Println("over init default Frondend config")
}

func initRoute() {
	log.Println("begin init default Route config")
	Rou = &BusAndRoutes{}
	fileName := "route.json"

	if local == 0 {
		if v, ok := os.LookupEnv("CONFIG_PATH_PREFIX"); ok {
			filePrefix = v
		}
		// read route
		data, err := ioutil.ReadFile(filePrefix + fileName)
		if err != nil {
			log.Println("route-initConf: read route.json error")
			log.Panic(err)
			return
		}
		err = jsoniter.Unmarshal(data, Rou)
		if err != nil {
			log.Println("route-initConf: unmarshal route.json error")
			log.Panic(err)
			return
		}
	} else {
		// read route
		data, err := ioutil.ReadFile("D:\\Hustbus\\src\\config\\route.json")
		if err != nil {
			log.Println("route-initConf: read route.json error")
			log.Panic(err)
			return
		}
		err = jsoniter.Unmarshal(data, Rou)
		if err != nil {
			log.Println("route-initConf: unmarshal route.json error")
			log.Panic(err)
			return
		}
	}
	log.Println("over init default Route config")
}

func initConf() {
	log.Println("begin init default config")
	Conf = &Config{}
	if local == 0 {
		fileName := "default.json"
		if v, ok := os.LookupEnv("CONFIG_PATH_PREFIX"); ok {
			filePrefix = v
		}
		if v, ok := os.LookupEnv("ENV"); ok {
			fileName = v + ".json"
			Conf.AppInfo.Env = v
		}
		// read default config
		data, err := ioutil.ReadFile(filePrefix + fileName)
		if err != nil {
			log.Println("config-initConf: read default.json error")
			log.Panic(err)
			return
		}
		err = jsoniter.Unmarshal(data, Conf)
		if err != nil {
			log.Println("config-initConf: unmarshal default.json error")
			log.Panic(err)
			return
		}
	} else {
		fileName := "D:\\Hustbus\\src\\config\\local.json"
		data, err := ioutil.ReadFile(fileName)
		if err != nil {
			log.Println("config-initConf: read default.json error")
			log.Panic(err)
			return
		}
		err = jsoniter.Unmarshal(data, Conf)
		if err != nil {
			log.Println("config-initConf: unmarshal default.json error")
			log.Panic(err)
			return
		}
	}

	if v, ok := os.LookupEnv("WeixinAppID"); ok {
		Conf.Wechat.AppID = v
	}
	if v, ok := os.LookupEnv("WeixinAppSecret"); ok {
		Conf.Wechat.AppSecret = v
	}

	if v, ok := os.LookupEnv("QINIU_ACCESS_KEY"); ok {
		Conf.Qiniu.AccessKey = v
	}
	if v, ok := os.LookupEnv("QINIU_SECRET_KEY"); ok {
		Conf.Qiniu.SecretKey = v
	}
	if v, ok := os.LookupEnv("QINIU_BUCKET"); ok {
		Conf.Qiniu.Bucket = v
	}

	if v, ok := os.LookupEnv("Slogan"); ok {
		Conf.AppInfo.Slogan = v
	}

	if v, ok := os.LookupEnv("FromEmail"); ok {
		Conf.EmailInfo.To = []string{v}
		Conf.EmailInfo.From = v
	}
	if v, ok := os.LookupEnv("EmailAuthCode"); ok {
		Conf.EmailInfo.AuthCode = v
	}
	if v, ok := os.LookupEnv("ToEmail"); ok {
		Conf.EmailInfo.To = strings.Fields(v)
	}
	if v, ok := os.LookupEnv("EmailHost"); ok {
		Conf.EmailInfo.Host = v
	}

	if v, ok := os.LookupEnv("MONGO_INITDB_ROOT_USERNAME"); ok {
		Conf.DB.User = v
	}
	if v, ok := os.LookupEnv("MONGO_INITDB_ROOT_PASSWORD"); ok {
		Conf.DB.PW = v
	}
	if v, ok := os.LookupEnv("MONGO_INITDB_DATABASE"); ok {
		Conf.DB.DBName = v
	}
	if v, ok := os.LookupEnv("RedisPass"); ok {
		Conf.Redis.PW = v
	}

	log.Println("over init default config")
}
